package com.me.study.jdk8.date;

import org.junit.Assert;
import org.junit.Test;

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

/**
 * ZoneId 表示时区， ZoneOffset 表示 UTC 偏移量
 *
 * LocalDateTime  = LocalDate + LocalTime
 * OffsetDateTime = LocalDateTime + ZoneOffset
 * ZonedDateTime  = OffsetDateTime + ZoneId
 */
public class ZonedDateTimeTest {

    /**
     * TODO
     *  1，Z、ZZ、ZZZ 是旧的 jdk格式，在 DateTimeFormatter、SimpleDateFormat 中他们是相同的，格式化之后都是 `+0000`、`+0800`
     *  2，DateTimeFormatter 是 jdk8 的类，提供了 ISO 8601 的完整支持；
     *  3，x、xx、xxx、X、XX、XXX 都是 ISO 8601时区格式。他们对于 UTC时间存在细微差别，其他一致：
     *      -- `x`   对于任何时区都是 `+00`
     *      -- `xx`  对于任何时区都是 `+0000`
     *      -- `xxx` 对于任何时区都是 `+00:00`
     *      -- `X`   对于  东八区 是 `+00`，   对于 UTC 则是 `Z`
     *      -- `XX`  对于  东八区 是 `+0000`， 对于 UTC 则是 `Z`
     *      -- `XXX` 对于  东八区 是 `+00:00`，对于 UTC 则是 `Z`
     *
     * 对于 ZoneOffset.ofHours(0)，
     * `x` 模板格式化为               `+00`
     * `xx` 模板格式化为              `+0000`
     * `xxx` 模板格式化为             `+00:00`
     * `Z` 模板格式化为               `+0000`
     * `ZZZ` 模板格式化为             `+0000`
     *
     * 对于 ZoneOffset.ofHours(+8)，
     * `x` 模板格式化为               `+08`
     * `xx` 模板格式化为              `+0800`
     * `xxx` 模板格式化为             `+08:00`
     * `Z` 模板格式化为               `+0800`
     * `ZZZ` 模板格式化为             `+0800`
     *
     * 对于 ZoneOffset.ofHours(0)，
     * `X`  模板格式化为               `Z`
     * `XX` 模板格式化为               `Z`
     * `XXX` 模板格式化为              `Z`
     * 对于 ZoneOffset.ofHours(+8)，
     * `X`  模板格式化为               `+08`
     * `XX` 模板格式化为               `+0800`
     * `XXX` 模板格式化为              `+08:00`
     *
     */
    private static final DateTimeFormatter F_x =   DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss 'GMT'x");
    private static final DateTimeFormatter F_xx =  DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss 'GMT'xx");
    private static final DateTimeFormatter F_xxx = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss 'GMT'xxx");

    private static final DateTimeFormatter F_X =   DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss 'GMT'X");
    private static final DateTimeFormatter F_XX =  DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss 'GMT'XX");
    private static final DateTimeFormatter F_XXX = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss 'GMT'XXX");

    private static final DateTimeFormatter F_Z =   DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss 'GMT'Z");
    private static final DateTimeFormatter F_ZZ =  DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss 'GMT'ZZ");
    private static final DateTimeFormatter F_ZZZ = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss 'GMT'ZZZ");

    @Test
    public void formatUTC() {
        LocalDateTime localDateTime = LocalDateTime.of(2023, 10, 19, 20, 0, 59);
        Assert.assertEquals("解析 GMT时区", "2023-10-19T20:00:59", localDateTime.toString());
        OffsetDateTime offsetDateTime = OffsetDateTime.of(localDateTime, ZoneOffset.ofHours(0));

        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMT+00", F_x.format(offsetDateTime));
        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMT+0000", F_xx.format(offsetDateTime));
        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMT+00:00", F_xxx.format(offsetDateTime));

        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMTZ", F_X.format(offsetDateTime));
        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMTZ", F_XX.format(offsetDateTime));
        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMTZ", F_XXX.format(offsetDateTime));

        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMT+0000", F_Z.format(offsetDateTime));
        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMT+0000", F_ZZ.format(offsetDateTime));
        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMT+0000", F_ZZZ.format(offsetDateTime));
    }

    @Test
    public void formatShanghai() {
        LocalDateTime localDateTime = LocalDateTime.of(2023, 10, 19, 20, 0, 59);
        Assert.assertEquals("解析 GMT时区", "2023-10-19T20:00:59", localDateTime.toString());
        OffsetDateTime offsetDateTime = OffsetDateTime.of(localDateTime, ZoneOffset.ofHours(+8));

        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMT+08", F_x.format(offsetDateTime));
        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMT+0800", F_xx.format(offsetDateTime));
        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMT+08:00", F_xxx.format(offsetDateTime));

        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMT+08", F_X.format(offsetDateTime));
        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMT+0800", F_XX.format(offsetDateTime));
        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMT+08:00", F_XXX.format(offsetDateTime));

        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMT+0800", F_Z.format(offsetDateTime));
        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMT+0800", F_ZZ.format(offsetDateTime));
        Assert.assertEquals("解析 GMT时区", "2023-10-19 20:00:59 GMT+0800", F_ZZZ.format(offsetDateTime));
    }

    @Test
    public void parse() {
        String str = "2020-09-12T00:00:00+08:00";
        OffsetDateTime odt = OffsetDateTime.parse(str);
        System.out.println(odt.toLocalDateTime());// 偏移时间转换成本地时间，2020-09-12T00:00

        // UTC时间字符串
        String utcTimeString = "2024-02-22 00:00Z";
        // 解析 UTC时间，并转换到东八区时间
        ZonedDateTime utcDateTime = ZonedDateTime.parse(utcTimeString, DateTimeFormatter.ofPattern("yyyy-MM-d HH:mmXXX"));
        ZonedDateTime shanghaiDateTime = utcDateTime.withZoneSameInstant(ZoneId.of("Asia/Shanghai"));

        // 转换为所需格式（如果需要的话）
        String formattedShanghaiTime = shanghaiDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm XXX"));
        System.out.println("转换后的东八区时间为：" + formattedShanghaiTime);// 2024-02-22 08:00 +08:00
    }

}
